package com.juyu.miliao.api.config;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.ContentTypeDelegatingMessageConverter;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.SimpleMessageConverter;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;

@Configuration
public class RabbitMQConfig {
	@Resource
	private RabbitProperties props;
	@Resource
	private ObjectMapper objectMapper;
	@Resource
	private RabbitExceptionHandler rabbitExceptionHandler;
    
    @Bean
    public CachingConnectionFactory connectionFactory(){
    	CachingConnectionFactory connectionFactory = new CachingConnectionFactory(props.getHost(), props.getPort());
    	connectionFactory.setUsername(props.getUsername());
    	connectionFactory.setPassword(props.getPassword());
    	connectionFactory.setPublisherConfirms(true);
    	connectionFactory.setPublisherReturns(true);
    	connectionFactory.setChannelCacheSize(100);
    	return connectionFactory;
    }
    
    @Bean
    public RabbitAdmin rabbitAdmin(){
    	RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory());
    	rabbitAdmin.setIgnoreDeclarationExceptions(false);
    	rabbitAdmin.declareExchange(new FanoutExchange("userSpendExchange", true, false));
        rabbitAdmin.declareExchange(new DirectExchange("EXCHANGE_ONE_TO_ONR_ROOM", true, false));
        rabbitAdmin.declareExchange(new FanoutExchange("exchange.fanout.robot.msg.login", true, false));
    	return rabbitAdmin;
    }
    
    private ObjectMapper objectMapper(){
		ObjectMapper objectMapper = new ObjectMapper()
        		.enable(SerializationFeature.WRITE_ENUMS_USING_INDEX)
        		.enable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN)
				.registerModule(new ParameterNamesModule())
				.registerModule(new Jdk8Module())
				.registerModule(new JavaTimeModule())
				.setSerializationInclusion(Include.NON_EMPTY);
		return objectMapper;
    }

    @Bean
    public SimpleMessageConverter simpleMessageConverter() {
        SimpleMessageConverter simpleMessageConverter = new SimpleMessageConverter();
        simpleMessageConverter.setDefaultCharset("UTF-8");
        return simpleMessageConverter;
    }

    @Bean
    public Jackson2JsonMessageConverter jackson2JsonMessageConverter() {
        Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter(objectMapper);
        return jackson2JsonMessageConverter;
    }

    @Bean
    public ContentTypeDelegatingMessageConverter contentTypeDelegatingMessageConverter() {
        ContentTypeDelegatingMessageConverter converter = new ContentTypeDelegatingMessageConverter();
        converter.addDelegate(MessageProperties.CONTENT_TYPE_TEXT_PLAIN, simpleMessageConverter());
        converter.addDelegate(MessageProperties.CONTENT_TYPE_JSON, jackson2JsonMessageConverter());
        return converter;
    }
    
    @Bean
    public RabbitTemplate rabbitTemplate(){
    	RabbitTemplate rabbitTemplate = rabbitAdmin().getRabbitTemplate();
    	rabbitTemplate.setMandatory(true);
    	rabbitTemplate.setMessageConverter(contentTypeDelegatingMessageConverter());
    	rabbitTemplate.setReturnCallback(new RabbitMQReturnCallback());
    	rabbitTemplate.setConfirmCallback(new RabbitMQConfirmCallback());
    	return rabbitTemplate;
    }

    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory());
        factory.setMessageConverter(contentTypeDelegatingMessageConverter());
        factory.setErrorHandler(rabbitExceptionHandler);
        return factory;
    }

    @Bean
    public Queue videoQueue() {
        return new Queue("home.video.id", true);
    }

    @Bean
    public Queue UserQueue() {
        return new Queue("home.user.id", true);
    }

    @Bean
    public Queue stopRobotMessageQueue(){
        return new Queue("queue.undrable.miliao.robot.stop.register",false);
    }



    @Bean("REGISTER_FANOUT_EXCHANGE")
    public FanoutExchange fanoutExchange(){
        return (FanoutExchange) ExchangeBuilder.fanoutExchange("REGISTER_FANOUT_EXCHANGE").durable(true).build();
    }

	@Bean
	public DirectExchange robotExchange() {
		return new DirectExchange("miliao.robot.stop.exchange");
	}
//
//	@Bean
//	public Binding videoBinding() {
//		return BindingBuilder.bind(videoQueue()).to(topicExchange()).with("key.home.video");
//	}
//
//	@Bean
//	public Binding userBinding() {
//		return BindingBuilder.bind(UserQueue()).to(topicExchange()).with("key.home.user");
//	}
}